/*
 * LDIR
 * 
 * LDIR, a GPS cartography application built for Let's Do It Romania eco 
 * campaign.
 * Copyright (C) 2010 Genera Software <office@generasoftware.com>
 * 
 * http://generasoftware.com/
 * 
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 * Place, Suite 330, Boston, MA 02111-1307 USA
 */
#include "WSUtilities.h"
#include <EscapeUtils.h>

//////////////////////////////////////////////////////////////////////////
//			UTILITIES
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
HBufC8* GenerateSignatureStringLC( const TDesC8& aHttpMethod,
	const TDesC8& aResourceUri, const TDesC8& aConsumerKey,
	const TDesC8& aConsumerSecret, const TDesC8& aSignatureMethod,
	const TDesC8& aOAuthTimestamp, const TDesC8& aOAuthNonce )
	{
	HBufC8* signatureString = NULL;
	HBufC8* consumerKeyEncoded = EscapeUtils::EscapeEncodeL( aConsumerKey,
		EscapeUtils::EEscapeUrlEncoded );
	CleanupStack::PushL( consumerKeyEncoded );

	TInt baseStringNeedSize = KSignatureBaseStringFormat().Length()
		+ aHttpMethod.Length() + aResourceUri.Length()
		+ consumerKeyEncoded->Length() + aSignatureMethod.Length()
		+ aOAuthTimestamp.Length() + aOAuthNonce.Length();
	RBuf8 baseString;
	baseString.CreateMaxL( baseStringNeedSize );
	baseString.Format( KSignatureBaseStringFormat, &aHttpMethod, &aResourceUri,
		consumerKeyEncoded, &aSignatureMethod, &aOAuthTimestamp, &aOAuthNonce );
	CleanupStack::PopAndDestroy( consumerKeyEncoded );
	CleanupClosePushL( baseString );

	CHMAC* hmac = NULL;
	CMessageDigest* messageDigest = NULL;
	if ( aSignatureMethod.CompareF( KHMAC_SHA1 ) == 0 )
		messageDigest = CSHA1::NewL();
	else if ( aSignatureMethod.CompareF( KMD5 ) == 0 )
		messageDigest = CMD5::NewL();

	CleanupStack::PushL( messageDigest );
	hmac = CHMAC::NewL( aConsumerSecret, messageDigest );
	CleanupStack::Pop( messageDigest );
	CleanupStack::PushL( hmac );

	hmac->Update( baseString );
	HBufC8* signatureHash = HBufC8::NewL( hmac->HashSize() );
	signatureHash->Des().Copy( hmac->Final() );
	CleanupStack::PopAndDestroy( hmac );
	CleanupStack::PopAndDestroy(); //baseString
	CleanupStack::PushL( signatureHash );
	// Now Encode to Base64
	signatureString = HBufC8::NewL( ( 4 * signatureHash->Length() ) / 3 + 1 );
	TPtr8 signatureStringPtr = signatureString->Des();
	DoBase64Encoding( *signatureHash, signatureStringPtr );
	CleanupStack::PopAndDestroy( signatureHash );
	CleanupStack::PushL( signatureString );
	return signatureString;
	}

//////////////////////////////////////////////////////////////////////////
HBufC8* GenerateOAuthLC( const TDesC8& aRealm, const TDesC8& aConsumerKey,
	const TDesC8& aSignatureMethod, const TDesC8& aSignature,
	const TDesC8& aTimestamp, const TDesC8& aNonce )
	{
	HBufC8* signatureUrlEncoded = EscapeUtils::EscapeEncodeL( aSignature,
		EscapeUtils::EEscapeUrlEncoded );
	CleanupStack::PushL( signatureUrlEncoded );
	HBufC8* consumerKeyEncoded = EscapeUtils::EscapeEncodeL( aConsumerKey,
		EscapeUtils::EEscapeUrlEncoded );
	CleanupStack::PushL( consumerKeyEncoded );
	TInt neededSize = KOAuthStringFormat().Length() + aRealm.Length()
		+ consumerKeyEncoded->Length() + signatureUrlEncoded->Length()
		+ aSignature.Length() + aTimestamp.Length() + aNonce.Length();
	HBufC8* auth = HBufC8::NewLC( neededSize );
	auth->Des().Format( KOAuthStringFormat, &aRealm, consumerKeyEncoded,
		&aSignatureMethod, signatureUrlEncoded, &aTimestamp, &aNonce );
	CleanupStack::Pop( auth );
	CleanupStack::PopAndDestroy( 2, signatureUrlEncoded );
	CleanupStack::PushL( auth );
	return auth;
	}

//////////////////////////////////////////////////////////////////////////
void DoBase64Encoding( const TDesC8& aSourceData, TDes8& aEncodedData )
	{
	TImCodecB64 b64enc;
	b64enc.Initialise();
	b64enc.Encode( aSourceData, aEncodedData );
	}

//////////////////////////////////////////////////////////////////////////
void DoBase64Decoding( const TDesC8& aSourceData, TDes8& aDecodedData )
	{
	TImCodecB64 b64dec;
	b64dec.Initialise();
	b64dec.Decode( aSourceData, aDecodedData );
	}

//////////////////////////////////////////////////////////////////////////
TBuf8<KTimestampLen> GetTimestamp()
	{
	TBuf8<KTimestampLen> timestamp( _L8("") );
	TTime time;
	time.UniversalTime();
	TTimeIntervalSeconds seconds;
	time.SecondsFrom( TTime( TDateTime( 1970, EJanuary, 0, 0, 0, 0, 0 ) ),
		seconds );
	timestamp.Num( seconds.Int() );
	return timestamp;
	}

//////////////////////////////////////////////////////////////////////////
TBuf8<KTimestampLen> GetTimestamp( TTime& aTime )
	{
	TBuf8<KTimestampLen> timestamp( _L8("") );
	TTimeIntervalSeconds seconds;
	aTime.SecondsFrom( TTime( TDateTime( 1970, EJanuary, 0, 0, 0, 0, 0 ) ),
		seconds );
	timestamp.Num( seconds.Int() );
	return timestamp;
	}

// End of File
